#include "qgf_tile.h"
#include "algorithm"
#include "kf_memory_file.h"

TileLayer::TileLayer()
{
	m_worldWidth = 0;
	m_worldHeight = 0;
	m_tileOffsetX = 0;
	m_tileOffsetY = 0;
	m_tileIndentX = 0;
	m_tileIndentY = 0;
	m_panX = 0;
	m_panY = 0;
	m_data = 0;
}

void TileLayer::init(int wx, int wy)
{
	if(m_data)
	{
		if(m_worldWidth == wx && m_worldHeight == wy)
		{
			clear(0);
			return;
		}
		delete [] m_data;
	}
	m_data = new unsigned int[wx * wy];
	m_worldWidth = wx;
	m_worldHeight = wy;
	clear(0);
}

void TileLayer::addTiles(HGE *hge, HTEXTURE tiletexture, int tilewidth, int tileheight)
{
	if(m_textures.size()==0)
	{
		m_tileIndentX = 0;
		m_tileIndentY = 0;
		m_tileOffsetX = tilewidth;
		m_tileOffsetY = tileheight;
	}
	m_textures.push_back(TileTexture(tiletexture, hge->Texture_GetWidth(tiletexture), hge->Texture_GetHeight(tiletexture), tilewidth, tileheight));
}

void TileLayer::render(HGE *hge)
{
	hgeQuad q;
	q.blend = BLEND_DEFAULT;
	q.tex = m_textures[0].tiles;
	int sx = (m_panX-m_tileIndentX)/(m_tileOffsetX)-(m_textures[0].tileWidth-m_tileOffsetX)/m_tileOffsetX;
	int sy = (m_panY-m_tileIndentY)/(m_tileOffsetY)-(m_textures[0].tileHeight-m_tileOffsetY)/m_tileOffsetY;
	int ex = (m_panX+hge->System_GetState(HGE_SCREENWIDTH))/m_tileOffsetX+1;
	int ey = (m_panY+hge->System_GetState(HGE_SCREENHEIGHT))/m_tileOffsetY+1;
	if(sx<0) sx=0;
	if(sy<0) sy=0;
	if(ex>m_worldWidth-1) ex = m_worldWidth-1;
	if(ey>m_worldHeight-1) ey = m_worldHeight-1;
//	float tileX = 1.0/int(hge->Texture_GetWidth(m_textures[0].tiles)/m_textures[0].tileWidth);
//	float tileY = 1.0/int(hge->Texture_GetWidth(m_textures[0].tiles)/m_textures[0].tileWidth);
	float tileX = float(m_textures[0].tileWidth) / float(m_textures[0].imageWidth);
	float tileY = float(m_textures[0].tileHeight) / float(m_textures[0].imageHeight);
	for(int y=sy;y<=ey;y++)
	{
		for(int x=sx;x<=ex;x++)
		{
			int indexX = m_data[x+y*m_worldWidth]%m_textures[0].tilesAcross;
			int indexY = m_data[x+y*m_worldWidth]/m_textures[0].tilesAcross;
			q.v[0].col = 0xffffffff;
			q.v[0].x = x * m_tileOffsetX + (y&1)*m_tileIndentX - m_panX;
			q.v[0].y = y * m_tileOffsetY + (x&1)*m_tileIndentY - m_panY;
			q.v[0].z = 0;
			q.v[0].tx = indexX*tileX;
			q.v[0].ty = indexY*tileY;

			q.v[1].col = 0xffffffff;
			q.v[1].x = (x) * m_tileOffsetX + m_textures[0].tileWidth + (y&1)*m_tileIndentX - m_panX;
			q.v[1].y = y * m_tileOffsetY + (x&1)*m_tileIndentY - m_panY;
			q.v[1].z = 0;
			q.v[1].tx = (indexX+0.999)*tileX;
			q.v[1].ty = (indexY)*tileY;

			q.v[2].col = 0xffffffff;
			q.v[2].x = (x) * m_tileOffsetX + m_textures[0].tileWidth + (y&1)*m_tileIndentX - m_panX;
			q.v[2].y = (y) * m_tileOffsetY + m_textures[0].tileHeight + (x&1)*m_tileIndentY - m_panY;
			q.v[2].z = 0;
			q.v[2].tx = (indexX+0.999)*tileX;
			q.v[2].ty = (indexY+1)*tileY;

			q.v[3].col = 0xffffffff;
			q.v[3].x = x * m_tileOffsetX + (y&1)*m_tileIndentX - m_panX;
			q.v[3].y = (y) * m_tileOffsetY + m_textures[0].tileHeight + (x&1)*m_tileIndentY - m_panY;
			q.v[3].z = 0;
			q.v[3].tx = (indexX)*tileX;
			q.v[3].ty = (indexY+1)*tileY;

			hge->Gfx_RenderQuad(&q);
		}
	}
}

void TileLayer::setPan(int x, int y)
{
	m_panX = x;
	m_panY = y;
}

void TileLayer::setTileOffset(int x, int y)
{
	m_tileOffsetX = x;
	m_tileOffsetY = y;
}

void TileLayer::setTileIndent(int x, int y)
{
	m_tileIndentX = x;
	m_tileIndentY = y;
}

void TileLayer::clear(unsigned int t)
{
	for(int y=0; y < m_worldHeight; y++)
	{
		for(int x=0; x < m_worldWidth; x++)
		{
			m_data[x+y*m_worldHeight] = t;
		}
	}
}

kf::dword TileLayer::getTile(int x, int y)
{
	if(x >= 0 && x < m_worldWidth && y >=0 && y < m_worldHeight)
	{
		return m_data[x+y*m_worldWidth];
	}
	return 0;
}

void TileLayer::setTile(int x, int y, kf::dword t)
{
	if(x >= 0 && x < m_worldWidth && y >=0 && y < m_worldHeight)
	{
		m_data[x+y*m_worldWidth] = t;
	}
}

bool TileLayer::loadMap(std::string filename)
{
	kf::MemFile mf(filename);
	if(!mf.is_good()) return false;
	kf::MemBlock mb = mf.get_block();

	int width = mb.get_dword();
	int height = mb.get_dword();
	init(width,height);
	for(int y=0;y<height;y++)
	{
		for(int x=0;x<width;x++)
		{
			m_data[x+y*width] = mb.get_dword();
		}
	}
	return true;
}

